package randoop.test;

import randoop.sequence.ExecutableSequence;

/**
 * This {@code TestCheckGenerator} combines two generators, using the invalid and failure checks
 * from the first, and, if none of those, then returning the output of the second.
 */
public class ExtendGenerator extends TestCheckGenerator {

  private TestCheckGenerator firstGenerator;
  private TestCheckGenerator secondGenerator;

  /**
   * Creates a check generator that generates {@code TestChecks} for {@code ExecutableSequence}
   * objects using the two {@code TestCheckGenerator} objects. Returns checks produced by the
   * second, unless the first produces checks that either have error or invalid behavior.
   *
   * @param firstGenerator the visitor to identify error and invalid behaviors in the sequence
   * @param secondGenerator the visitor to identify other checks for the sequence
   */
  public ExtendGenerator(TestCheckGenerator firstGenerator, TestCheckGenerator secondGenerator) {
    this.firstGenerator = firstGenerator;
    this.secondGenerator = secondGenerator;
  }

  /**
   * {@inheritDoc}
   *
   * <p>Returns checks generated by the two {@code TestCheckGenerator} objects.
   *
   * @return if the first generator generated invalid or error checks, return those; otherwise,
   *     return the checks object produced by the second generator
   */
  @Override
  public TestChecks<?> generateTestChecks(ExecutableSequence eseq) {
    TestChecks<?> checks = firstGenerator.generateTestChecks(eseq);
    if (checks.hasInvalidBehavior() || checks.hasErrorBehavior()) {
      return checks;
    } else {
      TestChecks<?> secondChecks = secondGenerator.generateTestChecks(eseq);
      if (secondChecks.hasChecks()) {
        return secondGenerator.generateTestChecks(eseq);
      }
      return checks;
    }
  }

  @Override
  public boolean hasGenerator(Class<? extends TestCheckGenerator> genClass) {
    return firstGenerator.hasGenerator(genClass) || secondGenerator.hasGenerator(genClass);
  }
}
